package com.sharedmobility.servlet;

import com.google.gson.Gson;
import com.sharedmobility.dao.RentalDAO;
import com.sharedmobility.dao.VehicleDAO;
import com.sharedmobility.model.Rental;
import com.sharedmobility.model.Vehicle;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.math.BigDecimal;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;

@WebServlet("/api/rental/*")
public class RentalServlet extends HttpServlet {
    private final RentalDAO rentalDAO = new RentalDAO();
    private final VehicleDAO vehicleDAO = new VehicleDAO();
    private final Gson gson = new Gson();

    // 定义状态常量
    private static final int RENTAL_STATUS_IN_PROGRESS = 0;
    private static final int RENTAL_STATUS_COMPLETED = 1;
    private static final int RENTAL_STATUS_CANCELLED = 2;

    private static final int VEHICLE_STATUS_AVAILABLE = 0;
    private static final int VEHICLE_STATUS_IN_USE = 1;
    private static final int VEHICLE_STATUS_MAINTENANCE = 2;

    @Override
    public void init() throws ServletException {
        // Initialize any other necessary resources
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String pathInfo = request.getPathInfo();
        
        try {
            if ("/admin".equals(pathInfo)) {
                // 管理员页面
                handleAdminPage(request, response);
            } else if ("/list".equals(pathInfo)) {
                // 获取租赁列表
                handleRentalList(request, response);
            } else if ("/current".equals(pathInfo)) {
                // 获取当前用户的正在进行中的租赁
                handleCurrentRental(request, response);
            } else {
                // 获取单个租赁详情
                handleRentalDetail(request, response);
            }
        } catch (SQLException e) {
            sendErrorResponse(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        } catch (Exception e) {
            sendErrorResponse(response, HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");

        String pathInfo = request.getPathInfo();
        
        try {
            if ("/start".equals(pathInfo)) {
                handleStartRental(request, response);
            } else if ("/end".equals(pathInfo)) {
                handleEndRental(request, response);
            } else {
                throw new Exception("无效的请求路径");
            }
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", e.getMessage());
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write(gson.toJson(result));
        }
    }

    private void handleAdminPage(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException, SQLException {
        // 获取所有车辆信息
        List<Vehicle> vehicles = vehicleDAO.findAll(null, "id");
        request.setAttribute("vehicles", vehicles);

        // 获取租赁信息
        List<Rental> activeRentals = rentalDAO.findByStatus(RENTAL_STATUS_IN_PROGRESS);
        List<Rental> completedRentals = rentalDAO.findByStatus(RENTAL_STATUS_COMPLETED);
        request.setAttribute("activeRentals", activeRentals);
        request.setAttribute("completedRentals", completedRentals);

        // 计算统计信息
        int availableVehicles = 0;
        int inUseVehicles = 0;
        int maintenanceVehicles = 0;
        
        for (Vehicle vehicle : vehicles) {
            if (vehicle.getStatus() == VEHICLE_STATUS_AVAILABLE) {
                availableVehicles++;
            } else if (vehicle.getStatus() == VEHICLE_STATUS_IN_USE) {
                inUseVehicles++;
            } else if (vehicle.getStatus() == VEHICLE_STATUS_MAINTENANCE) {
                maintenanceVehicles++;
            }
        }
        
        request.setAttribute("availableVehicles", availableVehicles);
        request.setAttribute("inUseVehicles", inUseVehicles);
        request.setAttribute("maintenanceVehicles", maintenanceVehicles);

        // 转发到JSP页面
        request.getRequestDispatcher("/WEB-INF/views/rental/admin.jsp").forward(request, response);
    }

    private void handleRentalList(HttpServletRequest request, HttpServletResponse response) 
            throws SQLException, IOException {
        HttpSession session = request.getSession();
        Integer userId = (Integer) session.getAttribute("userId");
        
        if (userId == null) {
            sendErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, "用户未登录");
            return;
        }
        
        List<Rental> rentals = rentalDAO.findByUserId(userId);
        
        // 获取每个租赁对应的车辆信息
        for (Rental rental : rentals) {
            Vehicle vehicle = vehicleDAO.findById(rental.getVehicleId());
            if (vehicle != null) {
                rental.setVehicle(vehicle);
            }
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", rentals);
        
        sendJsonResponse(response, result);
    }

    /**
     * 处理获取当前进行中的租赁请求
     */
    private void handleCurrentRental(HttpServletRequest request, HttpServletResponse response) 
            throws SQLException, IOException {
        HttpSession session = request.getSession();
        Integer userId = (Integer) session.getAttribute("userId");
        
        if (userId == null) {
            sendErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, "用户未登录");
            return;
        }
        
        // 查询用户当前进行中的租赁
        List<Rental> activeRentals = rentalDAO.findActiveByUserId(userId);
        Map<String, Object> result = new HashMap<>();
        
        if (!activeRentals.isEmpty()) {
            Rental currentRental = activeRentals.get(0);
            
            // 获取关联的车辆信息
            Vehicle vehicle = vehicleDAO.findById(currentRental.getVehicleId());
            currentRental.setVehicle(vehicle);
            
            // 计算当前的临时费用
            if (currentRental.getStartTime() != null && vehicle != null) {
                long rentalDurationMinutes = TimeUnit.MILLISECONDS.toMinutes(
                    System.currentTimeMillis() - currentRental.getStartTime().getTime()
                );
                BigDecimal tempAmount = BigDecimal.valueOf(rentalDurationMinutes)
                    .multiply(vehicle.getPricePerMinute());
                currentRental.setEstimatedAmount(tempAmount);
            }
            
            result.put("success", true);
            result.put("data", currentRental);
            result.put("active", true);
        } else {
            result.put("success", true);
            result.put("active", false);
        }
        
        sendJsonResponse(response, result);
    }

    private void handleRentalDetail(HttpServletRequest request, HttpServletResponse response) 
            throws SQLException, IOException {
        String pathInfo = request.getPathInfo();
        
        if (pathInfo == null || pathInfo.equals("/")) {
            sendErrorResponse(response, HttpServletResponse.SC_BAD_REQUEST, "缺少租赁ID");
            return;
        }
        
        try {
            Integer rentalId = Integer.parseInt(pathInfo.substring(1));
            Rental rental = rentalDAO.findById(rentalId);
            
            if (rental == null) {
                sendErrorResponse(response, HttpServletResponse.SC_NOT_FOUND, "租赁记录不存在");
                return;
            }
            
            // 获取对应的车辆信息
            Vehicle vehicle = vehicleDAO.findById(rental.getVehicleId());
            rental.setVehicle(vehicle);
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("data", rental);
            
            sendJsonResponse(response, result);
        } catch (NumberFormatException e) {
            sendErrorResponse(response, HttpServletResponse.SC_BAD_REQUEST, "无效的租赁ID");
        }
    }

    /**
     * 处理开始租赁请求
     */
    private void handleStartRental(HttpServletRequest request, HttpServletResponse response) 
            throws Exception {
        // 获取当前登录用户ID
        HttpSession session = request.getSession();
        Integer userId = (Integer) session.getAttribute("userId");
        if (userId == null) {
            throw new Exception("用户未登录");
        }

        // 解析请求数据
        Map<String, Object> requestData = gson.fromJson(request.getReader(), Map.class);
        Integer vehicleId = ((Number) requestData.get("vehicleId")).intValue();

        // 检查车辆是否可用
        Vehicle vehicle = vehicleDAO.findById(vehicleId);
        if (vehicle == null) {
            throw new Exception("车辆不存在");
        }
        if (vehicle.getStatus() != VEHICLE_STATUS_AVAILABLE) {
            throw new Exception("车辆不可用");
        }

        // 检查用户是否有正在进行中的租赁
        List<Rental> activeRentals = rentalDAO.findActiveByUserId(userId);
        if (!activeRentals.isEmpty()) {
            throw new Exception("您有正在进行中的租赁，请先结束后再租用新车辆");
        }

        // 创建租赁记录
        Rental rental = new Rental();
        rental.setUserId(userId);
        rental.setVehicleId(vehicleId);
        rental.setStartTime(new Timestamp(System.currentTimeMillis()));
        
        // 设置起始位置
        String startLocation = null;
        if (vehicle.getLongitude() != null && vehicle.getLatitude() != null) {
            startLocation = String.format("POINT(%s %s)", 
                vehicle.getLongitude().toString(), vehicle.getLatitude().toString());
        }
        rental.setStartLocation(startLocation);
        
        // 设置状态为进行中
        rental.setStatus(RENTAL_STATUS_IN_PROGRESS);
        
        // 保存租赁记录
        Integer rentalId = rentalDAO.create(rental);
        if (rentalId == null) {
            throw new Exception("创建租赁记录失败");
        }
        rental.setId(rentalId);
        
        // 更新车辆状态
        vehicle.setStatus(VEHICLE_STATUS_IN_USE);
        vehicleDAO.update(vehicle);
        
        // 设置返回的车辆信息
        rental.setVehicle(vehicle);

        // 返回成功响应
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "租用成功");
        result.put("data", rental);
        
        response.getWriter().write(gson.toJson(result));
    }

    /**
     * 处理结束租赁请求
     */
    private void handleEndRental(HttpServletRequest request, HttpServletResponse response) 
            throws Exception {
        // 获取当前登录用户ID
        HttpSession session = request.getSession();
        Integer userId = (Integer) session.getAttribute("userId");
        if (userId == null) {
            throw new Exception("用户未登录");
        }

        // 解析请求数据
        Map<String, Object> requestData = gson.fromJson(request.getReader(), Map.class);
        Integer vehicleId = ((Number) requestData.get("vehicleId")).intValue();
        
        // 获取结束位置（如果有）
        Double endLongitude = null;
        Double endLatitude = null;
        if (requestData.containsKey("longitude") && requestData.containsKey("latitude")) {
            endLongitude = ((Number) requestData.get("longitude")).doubleValue();
            endLatitude = ((Number) requestData.get("latitude")).doubleValue();
        }

        // 获取车辆信息
        Vehicle vehicle = vehicleDAO.findById(vehicleId);
        if (vehicle == null) {
            throw new Exception("车辆不存在");
        }
        if (vehicle.getStatus() != VEHICLE_STATUS_IN_USE) {
            throw new Exception("该车辆未被租用");
        }

        // 查找用户当前的租赁记录
        List<Rental> activeRentals = rentalDAO.findActiveByUserId(userId);
        if (activeRentals.isEmpty()) {
            throw new Exception("没有找到进行中的租赁记录");
        }
        
        Rental rental = null;
        for (Rental r : activeRentals) {
            if (r.getVehicleId().equals(vehicleId)) {
                rental = r;
                break;
            }
        }
        
        if (rental == null) {
            throw new Exception("您没有租用该车辆");
        }

        // 设置结束时间
        Timestamp endTime = new Timestamp(System.currentTimeMillis());
        rental.setEndTime(endTime);
        
        // 设置结束位置
        String endLocation = null;
        if (endLongitude != null && endLatitude != null) {
            endLocation = String.format("POINT(%s %s)", endLongitude.toString(), endLatitude.toString());
        } else if (vehicle.getLongitude() != null && vehicle.getLatitude() != null) {
            // 如果请求中没有提供位置，使用车辆当前位置
            endLocation = String.format("POINT(%s %s)", 
                vehicle.getLongitude().toString(), vehicle.getLatitude().toString());
        }
        rental.setEndLocation(endLocation);
        
        // 计算租赁费用
        BigDecimal totalAmount = calculateRentalFee(rental, vehicle);
        rental.setTotalAmount(totalAmount);
        
        // 设置状态为已完成
        rental.setStatus(RENTAL_STATUS_COMPLETED);
        
        // 保存租赁记录
        boolean updated = rentalDAO.update(rental);
        if (!updated) {
            throw new Exception("更新租赁记录失败");
        }
        
        // 更新车辆状态和位置
        vehicle.setStatus(VEHICLE_STATUS_AVAILABLE);
        if (endLongitude != null && endLatitude != null) {
            vehicle.setLongitude(endLongitude);
            vehicle.setLatitude(endLatitude);
        }
        vehicleDAO.update(vehicle);
        
        // 设置返回的车辆信息
        rental.setVehicle(vehicle);

        // 返回成功响应
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "还车成功");
        result.put("data", rental);
        
        response.getWriter().write(gson.toJson(result));
    }
    
    /**
     * 计算租赁费用
     * @param rental 租赁记录
     * @param vehicle 车辆信息
     * @return 总费用
     */
    private BigDecimal calculateRentalFee(Rental rental, Vehicle vehicle) {
        // 如果开始时间或结束时间为null，返回0
        if (rental.getStartTime() == null || rental.getEndTime() == null) {
            return BigDecimal.ZERO;
        }
        
        // 计算租赁时长（分钟）
        long rentalDurationMs = rental.getEndTime().getTime() - rental.getStartTime().getTime();
        long minutes = TimeUnit.MILLISECONDS.toMinutes(rentalDurationMs);
        
        // 至少计算1分钟
        minutes = Math.max(1, minutes);
        
        // 计算总费用
        return BigDecimal.valueOf(minutes).multiply(vehicle.getPricePerMinute());
    }

    private String formatLocationString(String location) {
        if (location == null || location.trim().isEmpty()) {
            return null;
        }

        // 尝试解析POINT格式
        Pattern pattern = Pattern.compile("POINT\\s*\\(([-+]?\\d*\\.?\\d+)\\s+([-+]?\\d*\\.?\\d+)\\)");
        Matcher matcher = pattern.matcher(location.trim());
        
        if (matcher.matches()) {
            // 如果已经是POINT格式，直接返回格式化后的字符串
            return String.format("POINT(%s %s)", matcher.group(1), matcher.group(2));
        } else {
            // 尝试解析坐标对
            pattern = Pattern.compile("([-+]?\\d*\\.?\\d+)\\s*[,\\s]\\s*([-+]?\\d*\\.?\\d+)");
            matcher = pattern.matcher(location.trim());
            
            if (matcher.matches()) {
                // 转换为POINT格式
                return String.format("POINT(%s %s)", matcher.group(1), matcher.group(2));
            }
        }
        
        return null;
    }

    private void sendJsonResponse(HttpServletResponse response, Object data) throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(gson.toJson(data));
    }
    
    private void sendErrorResponse(HttpServletResponse response, int statusCode, String message) throws IOException {
        Map<String, Object> result = new HashMap<>();
        result.put("success", false);
        result.put("message", message);
        
        response.setStatus(statusCode);
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(gson.toJson(result));
    }

    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String pathInfo = request.getPathInfo();
        
        if (pathInfo == null || pathInfo.equals("/")) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        
        try {
            int rentalId = Integer.parseInt(pathInfo.substring(1));
            Rental rental = rentalDAO.findById(rentalId);
            
            if (rental == null) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            
            // 只能删除已完成的租赁记录
            if (rental.getStatus() != RENTAL_STATUS_COMPLETED) {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Can only delete completed rentals");
                return;
            }
            
            // 暂时不实现删除功能
            response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, "Delete function not implemented");
        } catch (SQLException e) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }
} 